package com.kefu.call.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.kefu.basic.mapper.BasicFieldConfigInfoMapper;
import com.kefu.basic.mapper.BasicServiceSummaryMapper;
import com.kefu.basic.mapper.BasicTagMapper;
import com.kefu.basic.model.BasicFieldConfigInfo;
import com.kefu.basic.model.BasicServiceSummary;
import com.kefu.basic.model.BasicTag;
import com.kefu.call.http.client.CtiClient;
import com.kefu.call.http.model.CtiBlackPhone;
import com.kefu.call.http.model.CtiResult;
import com.kefu.call.mapper.CallMakeCallMapper;
import com.kefu.call.mapper.CallStartMapper;
import com.kefu.call.mapper.CallTagRelMapper;
import com.kefu.call.model.CallMakeCall;
import com.kefu.call.model.CallStart;
import com.kefu.call.model.CallTagRel;
import com.kefu.call.vo.CallConnectParam.*;
import com.kefu.call.vo.CallMakeCallSearchVo;
import com.kefu.call.vo.CallStartSearchVo;
import com.kefu.common.context.KefuContext;
import com.kefu.common.exception.BusinessException;
import com.kefu.common.service.AbstractKefuService;
import com.kefu.common.util.Assert;
import com.kefu.common.util.DateUtils;
import com.kefu.common.util.JacksonUtil;
import com.kefu.crm.mapper.CrmCustomerMapper;
import com.kefu.crm.model.CrmCustomer;
import com.kefu.crm.service.CrmShareService;
import com.kefu.crm.utils.PhoneDat;
import com.kefu.sys.mapper.SysUserMapper;
import com.kefu.sys.model.SysUser;
import com.kefu.wo.mapper.WoInfoMapper;
import com.kefu.wo.model.WoInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CallConnectService extends AbstractKefuService<CallMakeCall> {
    @Resource
    private WoInfoMapper woInfoMapper;
    @Resource
    private CallMakeCallMapper callMakeCallMapper;
    @Autowired
    private CtiClient ctiClient;
    @Autowired
    private PhoneDat phoneDat;
    @Resource
    SysUserMapper sysUserMapper;
    @Resource
    private BasicTagMapper basicTagMapper;
    @Resource
    private CallTagRelMapper callTagRelMapper;
    @Resource
    CrmShareService crmShareService;
    @Resource
    private CrmCustomerMapper crmCustomerMapper;
    @Resource
    private CallStartMapper callStartMapper;
    @Resource
    private BasicServiceSummaryMapper basicServiceSummaryMapper;
    @Resource
    private BasicFieldConfigInfoMapper basicFieldConfigInfoMapper;

    public CallGetR getCall(CallGetP param) {
        CallGetR result = new CallGetR();
        if(StrUtil.isNotBlank(param.getPhone())){
            result.setPhoneAscription(phoneDat.getCity(param.getPhone()));
            CrmCustomer customer = crmShareService.findByPhone(param.getPhone());
            if (Objects.isNull(customer)) {
                return result;
            }
            result.setCustomer(customer);
            List<WoInfo> todoWoList = woInfoMapper.selectList(Wrappers.lambdaQuery(WoInfo.class)
                    .eq(WoInfo::getCustomerId, customer.getCustomerId()).le(WoInfo::getWoStatus, 3));
            result.setTodoWoList(todoWoList);
            result.setTodoWoNum(todoWoList.size());
        }
        return result;
    }

    public CrmCustomer blackUser(BlackUserP param) {
        CrmCustomer crmCustomer = crmCustomerMapper.selectByPrimaryKey(param.getCustomerId());
        Assert.isNull(crmCustomer, "客户信息异常！");
        crmCustomer.setCustomerStatus(0 == param.getBlackMode() ? 1 : 3);
        crmCustomer.setUpdateTime(DateUtil.current());
        crmCustomer.setUpdateUser(KefuContext.getUid());
        crmCustomerMapper.updateById(crmCustomer);
        log.info("呼叫弹屏取消拉黑客户黑名单信息，客户信息 : {}", JacksonUtil.toString(crmCustomer));
        return crmCustomer;
    }


    public Page<CallMakeCall> callMakeCallList(CallMakeCallSearchVo param) {
        if(StrUtil.isBlank(param.getAgentId())&& StrUtil.isNotBlank(param.getAgentJobno())){
            //如果没有坐席id，用工号来查询
            SysUser sysUser  = sysUserMapper.selectOne(Wrappers.lambdaQuery(SysUser.class)
                    .eq(SysUser::getUserJobno,param.getAgentJobno()).eq(SysUser::getTenantId,KefuContext.getTid())
                    .last("limit 1"));
            if (sysUser!=null){
                param.setAgentId(sysUser.getUserId());
            }
        }
        Page<CallMakeCall> page = new Page<>(param.getPageNo(), param.getPageSize(), param.getPageSize() <= 100);
        page = callMakeCallMapper.selectPage(page, param.lambdaQuery());
        for (CallMakeCall callMakeCall : page.getRecords()) {
            List<CallTagRel> callTagRels = callTagRelMapper.selectList(Wrappers.lambdaQuery(CallTagRel.class)
                    .eq(CallTagRel::getCallId, callMakeCall.getCallId()));
            if (CollUtil.isNotEmpty(callTagRels)) {
                List<BasicTag> basicTags = basicTagMapper.selectList(Wrappers.lambdaQuery(BasicTag.class)
                        .in(BasicTag::getTagId, callTagRels.stream().map(CallTagRel::getTagId).collect(Collectors.toList())));
                callMakeCall.setBasicTag(basicTags);
            }
        }
        return page;
    }

    public Page<CallStart> callStartList(CallStartSearchVo param) {
        Page<CallStart> page = new Page<>(param.getPageNo(), param.getPageSize(), param.getPageSize() <= 100);
        page = callStartMapper.selectPage(page, param.lambdaQuery());
        for (CallStart callStart : page.getRecords()) {
            List<CallTagRel> callTagRels = callTagRelMapper.selectList(Wrappers.lambdaQuery(CallTagRel.class)
                    .eq(CallTagRel::getCallId, callStart.getCallId()));
            if (CollUtil.isNotEmpty(callTagRels)) {
                List<BasicTag> basicTags = basicTagMapper.selectList(Wrappers.lambdaQuery(BasicTag.class)
                        .in(BasicTag::getTagId, callTagRels.stream().map(CallTagRel::getTagId).collect(Collectors.toList())));
                callStart.setBasicTag(basicTags);
            }
            long startTime = DateUtils.parseToTime(callStart.getIvrStartTime());
            Long endTime = null;
            if (StrUtil.isNotBlank(callStart.getQueueStartTime())) {
                endTime = DateUtils.parseToTime(callStart.getQueueStartTime());
            } else {
                if (StrUtil.isNotBlank(callStart.getCallEndTime())) {
                    endTime = DateUtils.parseToTime(callStart.getCallEndTime());
                }
            }
            if (Objects.isNull(endTime)) {
                log.info("呼入回调:{}, 无法计算坐席排队时长,{},{}",
                        callStart.getOid(), callStart.getQueueStartTime(), callStart.getCallEndTime());
            }
            if (endTime >= startTime) {
                callStart.setIvrDurationTime(Convert.toInt((endTime - startTime) / 1000));
            }
        }
        return page;
    }

    public List<CallHistoryR> callHistoryList(CallHistoryP param) {
        List<CallHistoryR> result = Lists.newArrayList();
        // 查询呼出记录
        LambdaQueryWrapper<CallMakeCall> out = Wrappers.lambdaQuery(CallMakeCall.class);
        out.eq(CallMakeCall::getCompany, KefuContext.getTid());
        out.eq(CallMakeCall::getCalleeNumber, param.getPhone());
        out.eq(StrUtil.isNotBlank(param.getTaskDetailId()), CallMakeCall::getTaskDetailId, param.getTaskDetailId());
        out.orderByDesc(CallMakeCall::getRingTime).last("limit 100");
        List<CallMakeCall> callMakeCallList = callMakeCallMapper.selectList(out);
        callMakeCallList.forEach(i -> {
            i.setCallType("呼出");
            i.setAnswerTime(i.getRingTime());
        });
        List<CallHistoryR> callHistoryRListOut = BeanUtil.copyToList(callMakeCallList, CallHistoryR.class);
        result.addAll(callHistoryRListOut);
        // 查询呼入纪录
        LambdaQueryWrapper<CallStart> in = Wrappers.lambdaQuery(CallStart.class);
        in.eq(CallStart::getCompany, KefuContext.getTid());
        in.eq(CallStart::getCallerNumber, param.getPhone());
        in.orderByDesc(CallStart::getIvrStartTime).last("limit 100");
        List<CallStart> callStartList = callStartMapper.selectList(in);
        callStartList.forEach(i -> {
            i.setCallType("呼入");
            i.setAnswerTime(i.getIvrStartTime());
        });
        List<CallHistoryR> callHistoryRListIn = BeanUtil.copyToList(callStartList, CallHistoryR.class);
        result.addAll(callHistoryRListIn);
        result = result.stream().sorted(Comparator.comparing(CallHistoryR::getAnswerTime).reversed()).collect(Collectors.toList());
        return result;
    }


    public CallDetailR callDetail(CallDetailP param) {
        CallDetailR callDetail = null;
        if ("呼出".equals(param.getCallType())) {
            CallMakeCall callMakeCall = callMakeCallMapper.selectFirst(Wrappers.lambdaQuery(CallMakeCall.class)
                    .eq(CallMakeCall::getCompany, KefuContext.getTid())
                    .eq(CallMakeCall::getCallId, param.getCallId()));
            if (Objects.nonNull(callMakeCall)) {
                callDetail = BeanUtil.toBean(callMakeCall, CallDetailR.class);
                callDetail.setRecordUrl(callMakeCall.getRecordUrl());
                callDetail.setCallStartTime(callMakeCall.getAnswerTime());
                callDetail.setCallEndTime(callMakeCall.getCallHangupTime());
                callDetail.setLevelName(callMakeCall.getLevelName());
                callDetail.setCustomerPhoneCarrier(phoneDat.getCity(callMakeCall.getCalleeNumber()));
            }
        }
        if ("呼入".equals(param.getCallType())) {
            CallStart callStart = callStartMapper.selectFirst(Wrappers.lambdaQuery(CallStart.class)
                    .eq(CallStart::getCompany, KefuContext.getTid())
                    .eq(CallStart::getCallId, param.getCallId()));
            if (Objects.nonNull(callStart)) {
                callDetail = BeanUtil.toBean(callStart, CallDetailR.class);
                callDetail.setRecordUrl(callStart.getRecordUrl());
                callDetail.setCallStartTime(callStart.getIvrStartTime());
                callDetail.setCallId(callStart.getCallEndTime());
                callDetail.setLevelName(callStart.getLevelName());
                callDetail.setCustomerPhoneCarrier(phoneDat.getCity(callStart.getCalleeNumber()));
            }
        }
        if (Objects.isNull(callDetail)) {
            throw BusinessException.msg("查询失败!");
        }
        // 查询客户信息
        if (StrUtil.isNotBlank(callDetail.getCalleeNumber())) {
            List<CrmCustomer> crmCustomerList = crmCustomerMapper.selectList(Wrappers.lambdaQuery(CrmCustomer.class)
                    .eq(CrmCustomer::getPhone, callDetail.getCalleeNumber())
                    .eq(CrmCustomer::getTenantId, KefuContext.getTid()));
            if (null != crmCustomerList && crmCustomerList.size() > 0) {
                CrmCustomer crmCustomer = crmCustomerList.get(0);
                callDetail.setCustomerName(crmCustomer.getName());
                callDetail.setCustomerNick(crmCustomer.getNick());
                callDetail.setCustomerEmail(crmCustomer.getEmail());
                callDetail.setCustomerPhone(crmCustomer.getPhone());
                callDetail.setCustomerCompanyName(crmCustomer.getEnterpriseName());
            }
        }
        // 工单纪录
        List<WoInfo> woInfoList = woInfoMapper.selectList(Wrappers.lambdaQuery(WoInfo.class)
                .eq(WoInfo::getPartnerId, param.getCallId()));
        if (null != woInfoList && woInfoList.size() > 0) {
            WoInfo info = woInfoList.get(0);
            callDetail.setWoTitle(info.getWoTitle());
            callDetail.setWoContent(info.getWoContent());
            callDetail.setWoStatus(info.getWoStatus());
            callDetail.setWoLevel(info.getWoLevel());
            callDetail.setWoCreateName(info.getCreateName());
            callDetail.setWoDealUserName(info.getDealUserName());
        }
        // 服务总结
        BasicServiceSummary basicServiceSummary = basicServiceSummaryMapper.selectFirst(
                Wrappers.lambdaQuery(BasicServiceSummary.class).eq(BasicServiceSummary::getPid, param.getCallId()));
        if (Objects.nonNull(basicServiceSummary)) {
            callDetail.setServiceRemark(basicServiceSummary.getRemark());
            callDetail.setServiceTypeName(basicServiceSummary.getTypeName());
            callDetail.setServiceSolveFlag(basicServiceSummary.getSolveFlag());
        }
        return callDetail;
    }


    public void exportCallStartRecord(CallStartSearchVo searchVo, HttpServletResponse response) throws IOException {
        List<BasicFieldConfigInfo> basicFieldConfigInfoList = basicFieldConfigInfoMapper.selectList(Wrappers.lambdaQuery(BasicFieldConfigInfo.class)
                .eq(BasicFieldConfigInfo::getTenantId, KefuContext.getKefuContext().getTenantId())
                .eq(BasicFieldConfigInfo::getOperateType, 4));
        for (BasicFieldConfigInfo basicFieldConfigInfo : basicFieldConfigInfoList) {
            String value = basicFieldConfigInfo.getFieldValue();
            if (StrUtil.isNotBlank(value)) {
                basicFieldConfigInfo.setFileValueContainer(value.split(","));
            }
        }
        searchVo.setPageNo(1);
        searchVo.setPageSize(50000);
        Page<CallStart> list = callStartList(searchVo);
        List<Object[]> exportList = new ArrayList<>();
        Object[] title = {msg("呼叫时间"), msg("客户姓名"), msg("所属公司"),
                msg("主叫号码"), msg("被叫号码"), msg("号码归属地"), msg("呼入号码"), msg("技能组"), msg("坐席名称"),
                msg("振铃时间"), msg("振铃时长"), msg("摘机时间"), msg("通话时长"), msg("保持次数"),
                msg("保持时长"),msg("排队时长"), msg("结束时间"), msg("通话总时长"), msg("通话结果"),
                msg("满意度"), msg("业务类型"), msg("处理状态"), msg("总结备注"), msg("服务总结自定义字段"),
                msg("ivr轨迹"),msg("通话ID"), msg("原始ID")
        };
        exportList.add(title);
        if (null != list && list.getRecords() != null && list.getRecords().size() > 0) {
            for (CallStart i : list.getRecords()) {
                Integer solveFlag = i.getSolveFlag();
                String solve = (Objects.isNull(solveFlag) || 0 == solveFlag) ? "未解决" : "已解决";
                String summaryFields = i.getSummaryFields();
                if (StrUtil.isNotBlank(summaryFields)) {
                    summaryFields = StrUtil.replace(summaryFields, "id", "字段名称");
                    summaryFields = StrUtil.replace(summaryFields, "value", "字段值");
                    for (BasicFieldConfigInfo basicFieldConfigInfo : basicFieldConfigInfoList) {
                        summaryFields = StrUtil.replace(summaryFields, basicFieldConfigInfo.getFieldId(), basicFieldConfigInfo.getFieldName());
                    }
                }
                Object[] row = {i.getIvrStartTime(), i.getCustomerName(), i.getCustomerCompanyName(),
                        i.getCallerNumber(), i.getCalleeNumber(), i.getPhoneCarrier(), i.getCallinNumber(), i.getGroupName(), i.getAgentName(),
                        i.getAgentCalledTime(), i.getCalleeRingDurationTime(), i.getAgentAnsweredTime(), i.getTalkTime(), i.getHoldNum(),
                        i.getHoldTime(),i.getQueueDurationTime(), i.getHangupCauseTime(), i.getTalkTime(), i.getCancelReasonName(),
                        i.getLevelName(), i.getTypeName(), solve, i.getSummaryRemark(), summaryFields,
                        i.getIvrTrial(), i.getCallId(), i.getOriginalUuid()

                };
                exportList.add(row);
            }
        }
        csvWriter(exportList, response);
    }


    public void exportCallRecord(CallMakeCallSearchVo searchVo, HttpServletResponse response) throws IOException {

        List<BasicFieldConfigInfo> basicFieldConfigInfoList = basicFieldConfigInfoMapper.selectList(Wrappers.lambdaQuery(BasicFieldConfigInfo.class)
                .eq(BasicFieldConfigInfo::getTenantId, KefuContext.getKefuContext().getTenantId())
                .eq(BasicFieldConfigInfo::getOperateType, 4));
        for (BasicFieldConfigInfo basicFieldConfigInfo : basicFieldConfigInfoList) {
            String value = basicFieldConfigInfo.getFieldValue();
            if (StrUtil.isNotBlank(value)) {
                basicFieldConfigInfo.setFileValueContainer(value.split(","));
            }
        }
        List<Object[]> exportList = new ArrayList<>();
        Object[] title = {msg("拨打时间"), msg("客户姓名"), msg("坐席名称"),
                msg("主叫号码"), msg("外显号码"), msg("被叫号码"), msg("号码归属地"),
                msg("摘机时间"), msg("通话时长(秒)"), msg("结束时间"), msg("接听状态")
                , msg("处理状态"), msg("所属业务"), msg("总结备注"), msg("服务总结自定义字段")
        };
        exportList.add(title);
        searchVo.setPageNo(1);
        searchVo.setPageSize(50000);
        Page<CallMakeCall> list = callMakeCallList(searchVo);
        if (null != list && list.getRecords() != null && list.getRecords().size() > 0) {
            for (CallMakeCall i : list.getRecords()) {
                String answerStatus = "";
                if (StrUtil.isNotBlank(i.getAnswerStatus())) {
                    if ("1".equals(i.getAnswerStatus())) {
                        answerStatus = msg("已接听");
                    } else {
                        answerStatus = msg("未接听");
                    }
                }
                String SolveFlag = "";
                if (i.getSolveFlag() != null) {
                    if (i.getSolveFlag() == 0) {
                        SolveFlag = "未解决";
                    } else if (i.getSolveFlag() == 1) {
                        SolveFlag = "已解决";
                    } else {
                        SolveFlag = "";
                    }
                }
                String summaryFields = i.getSummaryFields();
                if (StrUtil.isNotBlank(summaryFields)) {
                    summaryFields = StrUtil.replace(summaryFields, "id", "字段名称");
                    summaryFields = StrUtil.replace(summaryFields, "value", "字段值");
                    for (BasicFieldConfigInfo basicFieldConfigInfo : basicFieldConfigInfoList) {
                        summaryFields = StrUtil.replace(summaryFields, basicFieldConfigInfo.getFieldId(), basicFieldConfigInfo.getFieldName());
                    }
                }
                Object[] row = {i.getRingTime(), i.getCustomerName(), i.getAgentName(),
                        i.getCallerNumber(), i.getGatewayNumber(), i.getCalleeNumber(), i.getPhoneCarrier(),
                        i.getCalleeAnswerTime(), i.getTalkTime(), i.getCallHangupTime(), answerStatus
                        , SolveFlag, i.getTypeName(), i.getSummaryRemark(), summaryFields
                };
                exportList.add(row);
            }
        }
        csvWriter(exportList, response);
    }


    public String makeFailCall(String callId) {
        // 统一添加到联系计划去处理
        List<CallStart> list = callStartMapper.selectList(Wrappers.lambdaQuery(CallStart.class).eq(CallStart::getCallId, callId));
        if (Objects.isNull(list) || list.size() == 0) {
            throw BusinessException.msg("通话信息异常");
        }
        // 获取到通话
        CallStart call = list.get(0);
        return null;
    }

    public void exportCallStartFailRecord(CallStartSearchVo search, HttpServletResponse response) throws IOException {
        search.setPageNo(1);
        search.setPageSize(50000);
        Page<CallStart> list = callStartList(search);
        List<Object[]> exportList = new ArrayList<>();
        Object[] title = {msg("开始时间"), msg("结束时间"), msg("主叫号码"),
                msg("被叫号码"), msg("Ivr节点"), msg("呼叫技能组"),
                msg("Ivr停留时间(秒)"), msg("排队开始时间"),
                msg("组排队时长"),
                msg("振铃开始时间"), msg("坐席振铃时长"), msg("总等待时长"),
                msg("呼损类型")
        };
        exportList.add(title);
        if (null != list && list.getRecords() != null && list.getRecords().size() > 0) {
            for (CallStart i : list.getRecords()) {
                Object[] row = {i.getStartTime(), i.getCallEndTime(), i.getCallerNumber(),
                        i.getCalleeNumber(), StrUtil.isBlank(i.getIvrTrial()) ? "--" : i.getIvrTrial(),
                        StrUtil.isBlank(i.getGroupName()) ? "--" : i.getGroupName(),
                        i.getIvrDurationTime(),
                        StrUtil.isBlank(i.getQueueStartTime()) ? "--" : i.getQueueStartTime(),
                        i.getQueueDurationTime(),
                        StrUtil.isBlank(i.getAgentCalledTime()) ? "--" : i.getAgentCalledTime(),
                        Objects.isNull(i.getCalleeRingDurationTime()) ? "--" : i.getCalleeRingDurationTime(),
                        Objects.isNull(i.getQueueDurationTime()) ? 0 : i.getQueueDurationTime() + (Objects.isNull(i.getCalleeRingDurationTime()) ? 0 : i.getCalleeRingDurationTime())
                        , Objects.isNull(i.getCallFailType()) || 0 == i.getCallFailType() ?
                        "Ivr放弃" : 5 == i.getCallFailType() ? "排队放弃" : 10 == i.getCallFailType() ? "振铃未接" : "其他"
                };
                exportList.add(row);
            }
        }
        csvWriter(exportList, response);
    }
}
